import 'package:backend.core/core/domain/config/config.dart';
import 'package:backend.core/core/domain/entities/google_play/google_play_one_time_purchased_item_info.dart';
import 'package:backend.core/core/domain/entities/google_play/google_play_purchased_item_acknowledgement_status.dart';
import 'package:backend.core/core/domain/entities/google_play/google_play_purchased_item_info.dart';
import 'package:backend.core/core/domain/entities/google_play/google_play_purchased_subscription_info.dart';
import 'package:backend.core/core/domain/repositories/google_play_purchased_item_info_repository/repository.dart';
import 'package:backend.core/core/domain/utils/either_extension.dart';
import 'package:backend.core/logger/logger.dart';
import 'package:backend.purchases/domain/entities/google_play_api/google_play_api_purchased_item_identifier.dart';
import 'package:backend.purchases/domain/helpers/google_play/update_google_play_one_time_purchased_item_info_from_api_one.dart';
import 'package:backend.purchases/domain/helpers/google_play/update_google_play_purchased_subscription_info_from_api_one.dart';
import 'package:backend.purchases/domain/repositories/google_play_api_purchased_item_repository/repository.dart';

abstract class RunGooglePlayApiPurchasedItemAcknowledgement {
  void call();
}

class RunGooglePlayApiPurchasedItemAcknowledgementImpl
    implements RunGooglePlayApiPurchasedItemAcknowledgement {
  const RunGooglePlayApiPurchasedItemAcknowledgementImpl({
    required GooglePlayApiPurchasedItemRepository googlePlayApiPurchasedItemRepository,
    required GooglePlayPurchasedItemInfoRepository googlePlayPurchasedItemInfoRepository,
    required UpdateGooglePlayOneTimePurchasedItemInfoFromApiOne
        updateGooglePlayOneTimePurchasedItemInfoFromApiOne,
    required UpdateGooglePlayPurchasedSubscriptionInfoFromApiOne
        updateGooglePlayPurchasedSubscriptionInfoFromApiOne,
  })  : _googlePlayApiPurchasedItemRepository = googlePlayApiPurchasedItemRepository,
        _googlePlayPurchasedItemInfoRepository = googlePlayPurchasedItemInfoRepository,
        _updateGooglePlayOneTimePurchasedItemInfoFromApiOne =
            updateGooglePlayOneTimePurchasedItemInfoFromApiOne,
        _updateGooglePlayPurchasedSubscriptionInfoFromApiOne =
            updateGooglePlayPurchasedSubscriptionInfoFromApiOne;

  final GooglePlayApiPurchasedItemRepository _googlePlayApiPurchasedItemRepository;
  final GooglePlayPurchasedItemInfoRepository _googlePlayPurchasedItemInfoRepository;
  final UpdateGooglePlayOneTimePurchasedItemInfoFromApiOne
      _updateGooglePlayOneTimePurchasedItemInfoFromApiOne;
  final UpdateGooglePlayPurchasedSubscriptionInfoFromApiOne
      _updateGooglePlayPurchasedSubscriptionInfoFromApiOne;

  @override
  void call() async {
    final Duration checkInterval;

    if (Config().environment.isProd) {
      checkInterval = const Duration(hours: 1);
    } else {
      checkInterval = const Duration(seconds: 10);
    }

    while (true) {
      try {
        await _runAcknowledgement();
      } catch (e, s) {
        Logger().e(null, e, s);
      }

      await Future.delayed(checkInterval);
    }
  }

  Future<void> _runAcknowledgement() async {
    final purchasedItemInfos =
        await _googlePlayPurchasedItemInfoRepository.findAllPurchasedItemInfos();

    final toBeAcknowledgedPurchasedItemInfos = purchasedItemInfos.where((purchasedItemInfo) {
      return purchasedItemInfo.acknowledgementStatus ==
          GooglePlayPurchasedItemAcknowledgementStatus.yetToBeAcknowledged;
    });

    for (final purchasedItemInfo in toBeAcknowledgedPurchasedItemInfos) {
      final purchasedItemIdentifier = GooglePlayApiPurchasedItemIdentifier(
        purchaseToken: purchasedItemInfo.purchaseToken,
        purchaseItemSku: purchasedItemInfo.purchaseItemSku,
      );

      late final GooglePlayPurchasedItemInfo updatedPurchasedItemInfo;

      if (purchasedItemInfo is GooglePlayOneTimePurchasedItemInfo) {
        final oneTimePurchasedItemInfo = purchasedItemInfo;

        final acknowledgementFailureOrResult =
            await _googlePlayApiPurchasedItemRepository.acknowledgeOneTimePurchasedItem(
          purchasedItemIdentifier: purchasedItemIdentifier,
        );

        var updatedOneTimePurchasedItemInfo = oneTimePurchasedItemInfo;

        if (acknowledgementFailureOrResult.isLeft()) {
          final acknowledgementFailure = acknowledgementFailureOrResult.asLeft();

          if (acknowledgementFailure
              is UnacknowledgeablePurchaseGooglePlayApiOneTimePurchasedItemAcknowledgementFailure) {
            updatedOneTimePurchasedItemInfo = updatedOneTimePurchasedItemInfo.copyWith(
              acknowledgementStatus: () =>
                  GooglePlayPurchasedItemAcknowledgementStatus.unacknowledgeable,
            );
          }
        }

        final failureOrUpdatedApiOneTimePurchasedItem =
            await _googlePlayApiPurchasedItemRepository.getOneTimePurchasedItem(
          purchasedItemIdentifier: purchasedItemIdentifier,
        );

        if (failureOrUpdatedApiOneTimePurchasedItem.isLeft()) {
          updatedPurchasedItemInfo = updatedOneTimePurchasedItemInfo;
        } else {
          final updatedApiOneTimePurchasedItem = failureOrUpdatedApiOneTimePurchasedItem.asRight();

          updatedPurchasedItemInfo = _updateGooglePlayOneTimePurchasedItemInfoFromApiOne(
            oneTimePurchasedItemInfo: updatedOneTimePurchasedItemInfo,
            updatedApiOneTimePurchasedItem: updatedApiOneTimePurchasedItem,
          );
        }
      } else if (purchasedItemInfo is GooglePlayPurchasedSubscriptionInfo) {
        final purchasedSubscriptionInfo = purchasedItemInfo;

        final acknowledgementFailureOrResult =
            await _googlePlayApiPurchasedItemRepository.acknowledgePurchasedSubscription(
          purchasedItemIdentifier: purchasedItemIdentifier,
        );

        var updatedPurchasedSubscriptionInfo = purchasedSubscriptionInfo;

        if (acknowledgementFailureOrResult.isLeft()) {
          final acknowledgementFailure = acknowledgementFailureOrResult.asLeft();

          if (acknowledgementFailure
              is UnacknowledgeablePurchaseGooglePlayApiPurchasedSubscriptionAcknowledgementFailure) {
            updatedPurchasedSubscriptionInfo = updatedPurchasedSubscriptionInfo.copyWith(
              acknowledgementStatus: () =>
                  GooglePlayPurchasedItemAcknowledgementStatus.unacknowledgeable,
            );
          }
        }

        final failureOrUpdatedApiPurchasedSubscription =
            await _googlePlayApiPurchasedItemRepository.getPurchasedSubscription(
          purchasedItemIdentifier: purchasedItemIdentifier,
        );

        if (failureOrUpdatedApiPurchasedSubscription.isLeft()) {
          updatedPurchasedItemInfo = updatedPurchasedSubscriptionInfo;
        } else {
          final updatedApiPurchasedSubscription =
              failureOrUpdatedApiPurchasedSubscription.asRight();

          updatedPurchasedItemInfo = _updateGooglePlayPurchasedSubscriptionInfoFromApiOne(
            purchasedSubscriptionInfo: updatedPurchasedSubscriptionInfo,
            updatedApiPurchasedSubscription: updatedApiPurchasedSubscription,
          );
        }
      }

      await _googlePlayPurchasedItemInfoRepository.upsertPurchasedItemInfo(
        purchasedItemInfo: updatedPurchasedItemInfo,
      );
    }
  }
}
